#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include "Comm.hpp"

using namespace std;

const static int Retry_Count = 5;

void Usage(const string &proc)
{
    cout << proc << " serverip serverport\n" << endl;
}

// // v1~v4版本的客户端
// // v1~v4版本的服务器都是长服务，客户端发送什么消息，服务器添加部分消息后就直接转发服务
// bool VisitServer(const string &serverip, uint16_t serverport,int* count)
// {
//     int n = 0 , m = 0;
//     string buffer;
//     char inbuffer[1024];
//     bool ret = true;
//     // 填充服务端信息
//     struct sockaddr_in server;
//     server.sin_family = AF_INET;
//     server.sin_port = htons(serverport);
//     inet_pton(AF_INET, serverip.c_str(), &server.sin_addr.s_addr);

//     // 创建套接字
//     int sockfd = socket(AF_INET, SOCK_STREAM, 0);
//     if (sockfd < 0)
//     {
//         cout << "create socket fail" << endl;
//         ret = false;
//         goto END;
//     }

//     // 建立连接
//     if (connect(sockfd, CONV(&server), sizeof(server)) != 0)
//     {
//         cout << "connect fail" << endl;
//         ret = false;
//         goto END;
//     }

//     *count = 1;

//     while(1)
//     {
//         // 向服务端发送信息
//         cout << "Please Enter# ";
//         getline(cin, buffer);
//         n = write(sockfd, buffer.c_str(), buffer.size());
//         if (n > 0)
//         {
//             m = read(sockfd, inbuffer, sizeof(inbuffer) - 1);
//             if (m > 0)
//             {
//                 inbuffer[m] = 0;
//                 cout <<  "get a message : " <<  inbuffer << endl;
//             }
//             else 
//             {
//                 ret = false;
//                 goto END;
//             }
//         }
//         else
//         {
//             ret = false;
//             goto END;
//         }
//     }
// END:
//     close(sockfd);
//     return ret;
// }

// v5版本客户端
// 短服务，服务一次后就退出
bool VisitServer(const string &serverip, uint16_t serverport,int* count)
{
    int n = 0 , m = 0;
    string buffer;
    char inbuffer[1024];
    bool ret = true;
    // 填充服务端信息
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(serverport);
    inet_pton(AF_INET, serverip.c_str(), &server.sin_addr.s_addr);

    // 创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        cout << "create socket fail" << endl;
        ret = false;
        goto END;
    }

    // 建立连接
    if (connect(sockfd, CONV(&server), sizeof(server)) != 0)
    {
        cout << "connect fail" << endl;
        ret = false;
        goto END;
    }

    *count = 1;

    // 获取服务列表
    m = read(sockfd, inbuffer, sizeof(inbuffer) - 1);
    if (m > 0)
    {
        inbuffer[m] = 0;
        cout << "server list : " << inbuffer << endl;
    }
    else
    {
        ret = false;
        goto END;
    }

    // 选择服务
    cout << "Please Select Server# ";
    getline(cin, buffer);
    if(buffer == "quit")
    {
        ret = true;
        goto END;
    }
    n = write(sockfd, buffer.c_str(), buffer.size());

    // 向服务端发送信息
    cout << "Enter> ";
    getline(cin, buffer);
    n = write(sockfd, buffer.c_str(), buffer.size());
    if (n > 0)
    {
        m = read(sockfd, inbuffer, sizeof(inbuffer) - 1);
        if (m > 0)
        {
            inbuffer[m] = 0;
            cout <<  inbuffer << endl;
        }
        else 
        {
            ret = false;
            goto END;
        }
    }
    else
    {
        ret = false;
        goto END;
    }

END:
    close(sockfd);
    return ret;
}




int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[0]);
        exit(1);
    }

    string serverip = argv[1];
    uint16_t serverport = stoi(argv[2]);

    // 断线重连
    int count = 1;
    while(count <= Retry_Count)
    {
        if(VisitServer(serverip,serverport,&count))
        {
            break;
        }
        else
        {
            sleep(1);
            cout << "server offline , retrying... , count : " << count << endl;
            count++;
        }
    }

    if(count >= Retry_Count)
        cout << "server offline , retrying... , count : " << count << endl;

    return 0;
}